package cn.sumpu.app.coolsk.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;

public class ExportExcel<T> {
	/**
	 * 这是一个通用的方法，利用了JAVA的反射机制，可以将放置在JAVA集合中并且符号一定条件的数据以EXCEL 的形式输出到指定IO设备上
	 * 
	 * @author grieous
	 * @param title
	 *            表格标题名
	 * @param headers
	 *            表格属性列名数组
	 * @param dataset
	 *            需要显示的数据集合,集合中一定要放置符合javabean风格的类的对象。此方法支持的
	 *            javabean属性的数据类型有基本数据类型及String,Date,byte[](图片数据)
	 * @param pattern
	 * 
	 **/
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public HSSFWorkbook createExcel(String title, String[] headers,
			Collection<T> dataSet, String datePattern) {
		try {
			HSSFWorkbook wb = new HSSFWorkbook();// 建立新HSSFWorkbook对象
			HSSFSheet sheet = wb.createSheet(title);// 建立新的sheet对象,工作表
			
			// 单元格样式
			HSSFCellStyle cellStyle = wb.createCellStyle();
			cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
			cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
			cellStyle.setWrapText(true);
			cellStyle.setLocked(false);
			// 产生表格标题行(第一行)
			HSSFRow row = sheet.createRow(0);
			for (int i = 0; i < headers.length; i++) {
				HSSFCell cell = row.createCell(i);
				cell.setCellStyle(cellStyle);
				HSSFRichTextString text = new HSSFRichTextString(headers[i]);
				cell.setCellValue(text);
			}
			// 列样式
			sheet.setColumnWidth(0, (short) (160 * 35.7));
			sheet.setDefaultColumnWidth(10);
			// 遍历集合数据，产生数据行
			Iterator<T> it = dataSet.iterator();
			int index = 0;
			while (it.hasNext()) {
				index++;
				row = sheet.createRow(index);
				row.setHeightInPoints(30);
				T t = (T) it.next();
				// 利用反射，根据javabean属性的先后顺序，动态调用getXxx()方法得到属性值
				Field[] fields = t.getClass().getDeclaredFields();
				for (int i = 0; i < fields.length; i++) {
					HSSFCell cell = row.createCell(i);
					
					cell.setCellType(HSSFCell.CELL_TYPE_STRING);//定义单元格为字符类型
					//cell.setEncoding(HSSFCell.ENCODING_UTF_16);//定义编码方式，为了支持中文，这里使用了ENCODING_UTF_16 
					cell.setCellStyle(cellStyle);//设置单元格格式
					Field field = fields[i];
					String fieldName = field.getName();
					String getMethodName = "get"
							+ fieldName.substring(0, 1).toUpperCase()
							+ fieldName.substring(1);
					Class tCls = t.getClass();
					Method getMethod = tCls.getMethod(getMethodName,new Class[] {});
					Object value = getMethod.invoke(t, new Object[] {});
					// 判断值的类型后进行强制类型转换
					String textValue = null;
					if (value instanceof String) {
						textValue = value.toString();
					}
					// 如果不是图片数据，就利用正则表达式判断textValue是否全部由数字组成
					if (textValue != null) {
						Pattern p = Pattern.compile("^//d+(//.//d+)?$");
						Matcher matcher = p.matcher(textValue);
						if (matcher.matches()) {
							// 是数字当作double处理
							cell.setCellValue(Double.parseDouble(textValue));
						} else {
							textValue = textValue.replaceAll("<br>", "\r\n");
							HSSFRichTextString richString = new HSSFRichTextString(
									textValue);
							cell.setCellValue(richString);
						}
					}

				}
				// 判断当前值是否与其 上一行同一列的值相同，相同则合并
				if (index > 1) {
					String lastvalue = sheet.getRow(index - 1).getCell(0).getStringCellValue();
					String currentValue = sheet.getRow(index).getCell(0).getStringCellValue();
					if (currentValue.equals(lastvalue)) {
						CellRangeAddress region=new CellRangeAddress(index - 1,index, 0, 0);
						//sheet.addMergedRegion(new CellRangeAddress(index - 1,index, 0, 0));
						sheet.addMergedRegion(region);
					}
				}
			}
			return wb;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

}